#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
项目分析器统一接口
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Set
from enum import Enum


class Platform(Enum):
    """平台类型"""
    IOS = "ios"
    ANDROID = "android"
    UNIFIED = "unified"
    MIXED = "mixed"
    REACT_NATIVE = "react-native"
    FLUTTER = "flutter"
    IONIC = "ionic"
    CORDOVA = "cordova"
    XAMARIN = "xamarin"
    NATIVESCRIPT = "nativescript"
    UNKNOWN = "unknown"


@dataclass
class AnalysisOptions:
    """分析选项"""
    use_cache: bool = True
    deep_analysis: bool = False  # 是否使用AST深度分析
    incremental: bool = True  # 是否使用增量分析
    analyze_dependencies: bool = True  # 是否分析依赖
    detect_platform: bool = True  # 是否检测平台
    max_workers: int = 4  # 并行分析的最大线程数

    def to_dict(self) -> dict:
        """转换为字典"""
        return {
            'use_cache': self.use_cache,
            'deep_analysis': self.deep_analysis,
            'incremental': self.incremental,
            'analyze_dependencies': self.analyze_dependencies,
            'detect_platform': self.detect_platform,
            'max_workers': self.max_workers
        }


@dataclass
class FileInfo:
    """文件信息"""
    path: str
    language: str
    size: int
    last_modified: float
    symbols_count: int = 0
    dependencies: List[str] = field(default_factory=list)


@dataclass
class DependencyInfo:
    """依赖信息"""
    dependencies: Dict[str, List[str]]  # 文件 -> 依赖文件列表
    circular_dependencies: List[List[str]]  # 循环依赖列表
    dependency_layers: List[List[str]]  # 依赖层级


@dataclass
class AnalysisResult:
    """分析结果"""
    platform: Platform = Platform.UNKNOWN
    files: Dict[str, FileInfo] = field(default_factory=dict)  # 文件路径 -> 文件信息
    symbols: Dict[str, Dict] = field(default_factory=dict)  # 符号类型 -> 符号字典
    dependencies: Optional[DependencyInfo] = None
    statistics: Dict = field(default_factory=dict)
    errors: List[str] = field(default_factory=list)
    warnings: List[str] = field(default_factory=list)
    metadata: Dict = field(default_factory=dict)

    def get_files_by_language(self, language: str) -> List[FileInfo]:
        """获取指定语言的文件"""
        return [f for f in self.files.values() if f.language == language]

    def get_total_symbols(self) -> int:
        """获取总符号数"""
        total = 0
        for symbol_dict in self.symbols.values():
            if isinstance(symbol_dict, dict):
                total += len(symbol_dict)
        return total

    def has_circular_dependencies(self) -> bool:
        """是否有循环依赖"""
        return bool(self.dependencies and self.dependencies.circular_dependencies)


class IProjectAnalyzer(ABC):
    """项目分析器统一接口"""

    @abstractmethod
    def analyze(self, project_path: str, options: AnalysisOptions = None) -> AnalysisResult:
        """
        分析项目

        Args:
            project_path: 项目路径
            options: 分析选项

        Returns:
            AnalysisResult: 分析结果
        """
        pass

    @abstractmethod
    def analyze_file(self, file_path: str, options: AnalysisOptions = None,
                     language_hint: Optional[str] = None) -> FileInfo:
        """
        分析单个文件

        Args:
            file_path: 文件路径
            options: 分析选项
            language_hint: 已知的语言标识（可选）

        Returns:
            FileInfo: 文件信息
        """
        pass

    @abstractmethod
    def detect_platform(self, project_path: str, platform_override: Optional[str] = None) -> Platform:
        """
        检测项目平台

        Args:
            project_path: 项目路径
            platform_override: 已检测到的平台字符串（可选，用于重复使用现有结果）

        Returns:
            Platform: 平台类型
        """
        pass

    @abstractmethod
    def analyze_dependencies(self, files: List[str], symbols: Optional[Dict] = None) -> DependencyInfo:
        """
        分析文件依赖关系

        Args:
            files: 文件路径列表
            symbols: 符号信息（可选，用于提高解析精度）

        Returns:
            DependencyInfo: 依赖信息
        """
        pass

    @abstractmethod
    def get_cached_result(self, project_path: str) -> Optional[AnalysisResult]:
        """
        获取缓存的分析结果

        Args:
            project_path: 项目路径

        Returns:
            Optional[AnalysisResult]: 缓存的结果，如果没有则返回None
        """
        pass

    @abstractmethod
    def save_cache(self, project_path: str, result: AnalysisResult):
        """
        保存分析结果到缓存

        Args:
            project_path: 项目路径
            result: 分析结果
        """
        pass
